package com.travel.modules.sys.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.travel.commons.shiro.ShiroUserGetter;
import com.travel.commons.utils.Constant;
import com.travel.commons.utils.DateUtils;
import com.travel.commons.utils.R;
import com.travel.commons.utils.SnowNoGenerator;
import com.travel.commons.validator.ValidatorUtils;
import com.travel.commons.validator.groups.AddGroup;
import com.travel.modules.sys.dto.SysConfigSafeDTO;
import com.travel.modules.sys.entity.SysUser;
import com.travel.modules.sys.service.SysConfigService;
import com.travel.modules.sys.service.SysUserService;
import com.travel.modules.sys.service.SysUserTokenService;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.Date;

/**
 * 系统-登录
 */
@RestController
@RequestMapping("/sys/user")
public class SysLoginController {
    @Resource
    private SysUserService sysUserService;

    @Resource
    private SysUserTokenService sysUserTokenService;

    @Resource
    private SysConfigService sysConfigService;

    /**
     * 用户登陆：loginName，password
     * @param form loginName
     * @return resetPw：1-需要重置密码
     *         token：需要缓存
     *         expire：token过期时间，一天
     */
    @RequestMapping("/login")
    public R login(@RequestBody SysUser form) {
        String loginName = form.getLoginName();
        SysUser user = sysUserService.getOne(new QueryWrapper<SysUser>().eq("mobile",loginName));
        if (user == null) {
            return R.error("账号不存在");
        }
        if (user.getStatus() == 0) {
            return R.error("该账号已停用，请联系管理员");
        }
        /* 账号未到解锁时间 */
        if (user.getPwLockDate() != null && user.getPwLockDate().after(new Date())) {
            return R.error("账号已被锁定，请在 " +
                    DateUtils.format(user.getPwLockDate(), DateUtils.DATE_TIME_PATTERN) + " 后登录");
        }
        SysConfigSafeDTO safeDTO = sysConfigService.getConfigObject(Constant.SYSTEM_CONFIG_SAFE, SysConfigSafeDTO.class);
        if (!user.getPassword().equals(new Sha256Hash(form.getPassword(), user.getSalt()).toHex())) {
            Date now = new Date();
            if (user.getPwErrorNum() == 0) {
                user.setPwErrorDate(now);
            }
            if (safeDTO.getLogin().getFail() <= user.getPwErrorNum() + 1) {// 密码错误次数达到了限定值
                user.setPwErrorDate(new Date(now.getTime() + safeDTO.getLogin().getLock() * 60000));
                user.setPwErrorNum(0);
                sysUserService.updateById(user);
                return R.error("密码错误次数已超过" + safeDTO.getLogin().getFail() + "次，请" + safeDTO.getLogin().getLock() + "分钟后重试");
            } else {
                if (user.getPwErrorDate() == null || user.getPwErrorDate().before(new Date(now.getTime() - safeDTO.getLogin().getLock() * 60000))) {
                    user.setPwErrorNum(1);
                    user.setPwErrorDate(now);
                } else {
                    user.setPwErrorNum(user.getPwErrorNum() + 1);
                }
                sysUserService.updateById(user);
                return R.error("密码错误，请重新输入(剩余" + (safeDTO.getLogin().getFail() - user.getPwErrorNum()) + "次机会)");
            }
        }
        user.setPwErrorNum(0);
        /* 生成token */
        R r = sysUserTokenService.generateToken(user.getId(), safeDTO.getPassword().getValid());
        sysUserService.updateById(user);
        r.put("roleType", user.getRoleId());
        return r.put("resetPw", user.getResetPw())
                .put("username", user.getUsername());
    }

    /**
     * 注册用户
     * @param form 必要信息：手机号、密码、角色类型
     */
    @RequestMapping("/sign")
    public R sign(@RequestBody SysUser form) {
        ValidatorUtils.validate(form, AddGroup.class);
        String mobile = form.getMobile();
        SysUser sysUser = sysUserService.getOne(new QueryWrapper<SysUser>().eq("mobile", mobile));
        if (!ObjectUtils.isEmpty(sysUser)) {// 如果有相同手机号
            return R.error("该手机号已经被注册");
        }

        form.setLoginName("u-" + new SnowNoGenerator().generate());
        /* 初始用户名 */
        form.setUsername((char) (Math.random() * 26 + 97) + mobile);
        form.setResetPw(0);
        form.setCreateTime(new Date());
        String salt = RandomStringUtils.randomAlphanumeric(20);
        form.setPassword(new Sha256Hash(form.getPassword(), salt).toHex());
        form.setSalt(salt);
        sysUserService.save(form);
        SysUser newUser = new SysUser();
        newUser.setMobile(form.getMobile());
        return R.ok().put("page", newUser);
    }

    /**
     * 登出
     */
    @RequestMapping("/logout")
    public R logout() {
        Integer id = ShiroUserGetter.getUserId();
        if (!ObjectUtils.isEmpty(id)) {
            sysUserTokenService.logout(id);
        }
        return R.ok();
    }
}
